1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.math;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static com.google.common.base.Preconditions.checkNotNull;
21 import static com.google.common.math.MathPreconditions.checkNoOverflow;
22 import static com.google.common.math.MathPreconditions.checkNonNegative;
23 import static com.google.common.math.MathPreconditions.checkPositive;
24 import static com.google.common.math.MathPreconditions.checkRoundingUnnecessary;
25 import static java.lang.Math.abs;
26 import static java.lang.Math.min;
27 import static java.math.RoundingMode.HALF_EVEN;
28 import static java.math.RoundingMode.HALF_UP;
29
30 import com.google.common.annotations.GwtCompatible;
31 import com.google.common.annotations.GwtIncompatible;
32 import com.google.common.annotations.VisibleForTesting;
33
34 import java.math.BigInteger;
35 import java.math.RoundingMode;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 @GwtCompatible(emulated = true)
52 public final class IntMath {
53
54
55
56
57
58
59
60
61
62 public static boolean isPowerOfTwo(int x) {
63 return x > 0 & (x & (x - 1)) == 0;
64 }
65
66
67
68
69
70
71 @VisibleForTesting
72 static int lessThanBranchFree(int x, int y) {
73
74
75 return ~~(x - y) >>> (Integer.SIZE - 1);
76 }
77
78
79
80
81
82
83
84
85 @SuppressWarnings("fallthrough")
86
87 public static int log2(int x, RoundingMode mode) {
88 checkPositive("x", x);
89 switch (mode) {
90 case UNNECESSARY:
91 checkRoundingUnnecessary(isPowerOfTwo(x));
92
93 case DOWN:
94 case FLOOR:
95 return (Integer.SIZE - 1) - Integer.numberOfLeadingZeros(x);
96
97 case UP:
98 case CEILING:
99 return Integer.SIZE - Integer.numberOfLeadingZeros(x - 1);
100
101 case HALF_DOWN:
102 case HALF_UP:
103 case HALF_EVEN:
104
105 int leadingZeros = Integer.numberOfLeadingZeros(x);
106 int cmp = MAX_POWER_OF_SQRT2_UNSIGNED >>> leadingZeros;
107
108 int logFloor = (Integer.SIZE - 1) - leadingZeros;
109 return logFloor + lessThanBranchFree(cmp, x);
110
111 default:
112 throw new AssertionError();
113 }
114 }
115
116
117 @VisibleForTesting static final int MAX_POWER_OF_SQRT2_UNSIGNED = 0xB504F333;
118
119
120
121
122
123
124
125
126 @GwtIncompatible("need BigIntegerMath to adequately test")
127 @SuppressWarnings("fallthrough")
128 public static int log10(int x, RoundingMode mode) {
129 checkPositive("x", x);
130 int logFloor = log10Floor(x);
131 int floorPow = powersOf10[logFloor];
132 switch (mode) {
133 case UNNECESSARY:
134 checkRoundingUnnecessary(x == floorPow);
135
136 case FLOOR:
137 case DOWN:
138 return logFloor;
139 case CEILING:
140 case UP:
141 return logFloor + lessThanBranchFree(floorPow, x);
142 case HALF_DOWN:
143 case HALF_UP:
144 case HALF_EVEN:
145
146 return logFloor + lessThanBranchFree(halfPowersOf10[logFloor], x);
147 default:
148 throw new AssertionError();
149 }
150 }
151
152 private static int log10Floor(int x) {
153
154
155
156
157
158
159
160 int y = maxLog10ForLeadingZeros[Integer.numberOfLeadingZeros(x)];
161
162
163
164
165 return y - lessThanBranchFree(x, powersOf10[y]);
166 }
167
168
169 @VisibleForTesting static final byte[] maxLog10ForLeadingZeros = {9, 9, 9, 8, 8, 8,
170 7, 7, 7, 6, 6, 6, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3, 3, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0};
171
172 @VisibleForTesting static final int[] powersOf10 = {1, 10, 100, 1000, 10000,
173 100000, 1000000, 10000000, 100000000, 1000000000};
174
175
176 @VisibleForTesting static final int[] halfPowersOf10 =
177 {3, 31, 316, 3162, 31622, 316227, 3162277, 31622776, 316227766, Integer.MAX_VALUE};
178
179
180
181
182
183
184
185
186
187
188 @GwtIncompatible("failing tests")
189 public static int pow(int b, int k) {
190 checkNonNegative("exponent", k);
191 switch (b) {
192 case 0:
193 return (k == 0) ? 1 : 0;
194 case 1:
195 return 1;
196 case (-1):
197 return ((k & 1) == 0) ? 1 : -1;
198 case 2:
199 return (k < Integer.SIZE) ? (1 << k) : 0;
200 case (-2):
201 if (k < Integer.SIZE) {
202 return ((k & 1) == 0) ? (1 << k) : -(1 << k);
203 } else {
204 return 0;
205 }
206 default:
207
208 }
209 for (int accum = 1;; k >>= 1) {
210 switch (k) {
211 case 0:
212 return accum;
213 case 1:
214 return b * accum;
215 default:
216 accum *= ((k & 1) == 0) ? 1 : b;
217 b *= b;
218 }
219 }
220 }
221
222
223
224
225
226
227
228
229 @GwtIncompatible("need BigIntegerMath to adequately test")
230 @SuppressWarnings("fallthrough")
231 public static int sqrt(int x, RoundingMode mode) {
232 checkNonNegative("x", x);
233 int sqrtFloor = sqrtFloor(x);
234 switch (mode) {
235 case UNNECESSARY:
236 checkRoundingUnnecessary(sqrtFloor * sqrtFloor == x);
237 case FLOOR:
238 case DOWN:
239 return sqrtFloor;
240 case CEILING:
241 case UP:
242 return sqrtFloor + lessThanBranchFree(sqrtFloor * sqrtFloor, x);
243 case HALF_DOWN:
244 case HALF_UP:
245 case HALF_EVEN:
246 int halfSquare = sqrtFloor * sqrtFloor + sqrtFloor;
247
248
249
250
251
252
253
254
255
256
257
258 return sqrtFloor + lessThanBranchFree(halfSquare, x);
259 default:
260 throw new AssertionError();
261 }
262 }
263
264 private static int sqrtFloor(int x) {
265
266
267 return (int) Math.sqrt(x);
268 }
269
270
271
272
273
274
275
276
277 @SuppressWarnings("fallthrough")
278 public static int divide(int p, int q, RoundingMode mode) {
279 checkNotNull(mode);
280 if (q == 0) {
281 throw new ArithmeticException("/ by zero");
282 }
283 int div = p / q;
284 int rem = p - q * div;
285
286 if (rem == 0) {
287 return div;
288 }
289
290
291
292
293
294
295
296
297 int signum = 1 | ((p ^ q) >> (Integer.SIZE - 1));
298 boolean increment;
299 switch (mode) {
300 case UNNECESSARY:
301 checkRoundingUnnecessary(rem == 0);
302
303 case DOWN:
304 increment = false;
305 break;
306 case UP:
307 increment = true;
308 break;
309 case CEILING:
310 increment = signum > 0;
311 break;
312 case FLOOR:
313 increment = signum < 0;
314 break;
315 case HALF_EVEN:
316 case HALF_DOWN:
317 case HALF_UP:
318 int absRem = abs(rem);
319 int cmpRemToHalfDivisor = absRem - (abs(q) - absRem);
320
321
322 if (cmpRemToHalfDivisor == 0) {
323 increment = (mode == HALF_UP || (mode == HALF_EVEN & (div & 1) != 0));
324 } else {
325 increment = cmpRemToHalfDivisor > 0;
326 }
327 break;
328 default:
329 throw new AssertionError();
330 }
331 return increment ? div + signum : div;
332 }
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350 public static int mod(int x, int m) {
351 if (m <= 0) {
352 throw new ArithmeticException("Modulus " + m + " must be > 0");
353 }
354 int result = x % m;
355 return (result >= 0) ? result : result + m;
356 }
357
358
359
360
361
362
363
364 public static int gcd(int a, int b) {
365
366
367
368
369
370 checkNonNegative("a", a);
371 checkNonNegative("b", b);
372 if (a == 0) {
373
374
375 return b;
376 } else if (b == 0) {
377 return a;
378 }
379
380
381
382
383 int aTwos = Integer.numberOfTrailingZeros(a);
384 a >>= aTwos;
385 int bTwos = Integer.numberOfTrailingZeros(b);
386 b >>= bTwos;
387 while (a != b) {
388
389
390
391
392
393
394
395 int delta = a - b;
396
397 int minDeltaOrZero = delta & (delta >> (Integer.SIZE - 1));
398
399
400 a = delta - minDeltaOrZero - minDeltaOrZero;
401
402
403 b += minDeltaOrZero;
404 a >>= Integer.numberOfTrailingZeros(a);
405 }
406 return a << min(aTwos, bTwos);
407 }
408
409
410
411
412
413
414 public static int checkedAdd(int a, int b) {
415 long result = (long) a + b;
416 checkNoOverflow(result == (int) result);
417 return (int) result;
418 }
419
420
421
422
423
424
425 public static int checkedSubtract(int a, int b) {
426 long result = (long) a - b;
427 checkNoOverflow(result == (int) result);
428 return (int) result;
429 }
430
431
432
433
434
435
436 public static int checkedMultiply(int a, int b) {
437 long result = (long) a * b;
438 checkNoOverflow(result == (int) result);
439 return (int) result;
440 }
441
442
443
444
445
446
447
448
449
450 public static int checkedPow(int b, int k) {
451 checkNonNegative("exponent", k);
452 switch (b) {
453 case 0:
454 return (k == 0) ? 1 : 0;
455 case 1:
456 return 1;
457 case (-1):
458 return ((k & 1) == 0) ? 1 : -1;
459 case 2:
460 checkNoOverflow(k < Integer.SIZE - 1);
461 return 1 << k;
462 case (-2):
463 checkNoOverflow(k < Integer.SIZE);
464 return ((k & 1) == 0) ? 1 << k : -1 << k;
465 default:
466
467 }
468 int accum = 1;
469 while (true) {
470 switch (k) {
471 case 0:
472 return accum;
473 case 1:
474 return checkedMultiply(accum, b);
475 default:
476 if ((k & 1) != 0) {
477 accum = checkedMultiply(accum, b);
478 }
479 k >>= 1;
480 if (k > 0) {
481 checkNoOverflow(-FLOOR_SQRT_MAX_INT <= b & b <= FLOOR_SQRT_MAX_INT);
482 b *= b;
483 }
484 }
485 }
486 }
487
488 @VisibleForTesting static final int FLOOR_SQRT_MAX_INT = 46340;
489
490
491
492
493
494
495
496
497 public static int factorial(int n) {
498 checkNonNegative("n", n);
499 return (n < factorials.length) ? factorials[n] : Integer.MAX_VALUE;
500 }
501
502 private static final int[] factorials = {
503 1,
504 1,
505 1 * 2,
506 1 * 2 * 3,
507 1 * 2 * 3 * 4,
508 1 * 2 * 3 * 4 * 5,
509 1 * 2 * 3 * 4 * 5 * 6,
510 1 * 2 * 3 * 4 * 5 * 6 * 7,
511 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8,
512 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9,
513 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10,
514 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11,
515 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 * 11 * 12};
516
517
518
519
520
521
522
523 @GwtIncompatible("need BigIntegerMath to adequately test")
524 public static int binomial(int n, int k) {
525 checkNonNegative("n", n);
526 checkNonNegative("k", k);
527 checkArgument(k <= n, "k (%s) > n (%s)", k, n);
528 if (k > (n >> 1)) {
529 k = n - k;
530 }
531 if (k >= biggestBinomials.length || n > biggestBinomials[k]) {
532 return Integer.MAX_VALUE;
533 }
534 switch (k) {
535 case 0:
536 return 1;
537 case 1:
538 return n;
539 default:
540 long result = 1;
541 for (int i = 0; i < k; i++) {
542 result *= n - i;
543 result /= i + 1;
544 }
545 return (int) result;
546 }
547 }
548
549
550 @VisibleForTesting static int[] biggestBinomials = {
551 Integer.MAX_VALUE,
552 Integer.MAX_VALUE,
553 65536,
554 2345,
555 477,
556 193,
557 110,
558 75,
559 58,
560 49,
561 43,
562 39,
563 37,
564 35,
565 34,
566 34,
567 33
568 };
569
570
571
572
573
574
575
576 public static int mean(int x, int y) {
577
578
579
580 return (x & y) + ((x ^ y) >> 1);
581 }
582
583 private IntMath() {}
584 }